-
-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bluetooth Device Pairing Infrastructure and Health Measurements #1
Conversation
…trol Point (#29) # Support Control Point Characteristics and implement Record Access Control Point ## ♻️ Current situation & Problem The Record Access Control Point characteristic is a standardized Bluetooth characteristic to model service-specific procedures for management of a set of data records. While the exact format is specific to the service specification using it, both the Glucose Monitor service and Enhanced Blood Pressure service define a similar format for the Record Access Control Point characteristic. Similar, Omron defines a custom service for their Blood Pressure Cuffs with a similar implementation of the Record Access Control Point characteristic. This PR implements a Record Access Control Point characteristic that is generic an can be instantiated with the respective service specification. Further, it instantiates it using the `GenericOperand` that is common to services like the Glucose Monitor and the Enhanced Blood Pressure service. An instantiation of the Omron option service is done in StanfordSpezi/SpeziDevices#1. To better support control point characteristics, this PR also adds a new `ControlPointCharacteristic` marker protocol that allows to access native support to sending requests and receiving the response to and from a control point characteristic (one async call instead of writing a value and waiting for the notification). ## ⚙️ Release Notes * Add new `ControlPointCharacteristic` marker protocol and a `sendRequest(_:timeout:)` accessor. * Add support for the `RecordAccessControlPoint` characteristic. ## 📚 Documentation Documentation catalog was updated to include those new symbols and new symbols were documented accordingly. ## ✅ Testing The new characteristic was fully unit tested. We added additional support within the `TestingSupport` SPI to make unit testing of control point characteristics easier. Functionality was validated against a Omron Bluetooth device for real-world testing. ## 📝 Code of Conduct & Contributing Guidelines By submitting creating this pull request, you agree to follow our [Code of Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md): - [x] I agree to follow the [Code of Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md).
# Support retrieving Peripherals ## ♻️ Current situation & Problem SpeziBluetooth is currently optimized for device discovery and ad-hoc connection establishment. However, when dealing with device pairing, one typically scans for nearby devices once and saving the peripheral identifier and perform long running connection attempts (e.g., calling [`retrievePeripherals(withidentifiers:)`](https://developer.apple.com/documentation/corebluetooth/cbcentralmanager/retrieveperipherals(withidentifiers:)) and calling connect()). Connecting a peripheral does not time out and is therefore the most efficient way of establishing Bluetooth connecting with a set of known Bluetooth devices. To support this use case, some modifications have been made to the underlying SpeziBluetooth infrastructure. New mechanisms were introduced to retrieve known peripherals (`BluetoothManager/retrievePeripheral(for:with:)` and `Bluetooth/retrieveDevice(for:as:)`). These device instances can stay allocated and SpeziBluetooth automatically frees resources once the framework user deallocates the peripheral instances. Several changes to the lifecycle handling of `BluetoothPeripheral`s and `BluetoothDevice`s have been made to support this new interfaces (e.g., carefully managing when objects are kept as strong references and when to reuse objects when, e.g., the same instance is getting discovered at the same time). ### SpeziDevices SpeziDevices is an upcoming library to encapsulates a lot of standardized device interactions. This PR is driven by a lot of requirements of this library. ## :gear: Release Notes * Support retrieving known peripherals using `BluetoothManager/retrievePeripheral(for:with:)` and `Bluetooth/retrieveDevice(for:as:)`. * The `BluetoothViews` target was removed and integrated into the `SpeziDevicesUI` of the SpezIDevices framework (see StanfordSpezi/SpeziDevices#1, **Breaking**). * The `BluetoothServices` target was renamed to `SpeziBluetoothServices` for more consistency (**Breaking**). * Add `accessory` discovery criteria. * New `nearby` and `lastActivity` state properties for peripherals and devices. * The peripheral name is now preferred with the `name` property and the `localName` property can now be accessed individually on a peripheral (**Breaking**). * Internally restructure discovery state into an `DiscoverySession` for better code overview. * Configuration options (like minimumRSSI and advertisementStaleInterval) are now passed directly to the `scanNearbyDevices(...)` methods and modifiers allowing for more dynamic configuration. * Adding `Bluetooth/stateSubscription` and `BluetoothManager/stateSubscription` to receive an AsyncStream of `BluetoothState` changes useful when required to observe CBCentral changes. * Adding `CharacteristicAccessor/subscription` and `DeviceStateAccessor/subscription` properties to receive an AsyncStream of changes to the characteristic value or device state. * `onChange(initial:perform:)` methods now must not be set up in the initializer anymore and must not create strong self references. Instead setup onChange handlers in the `configure()` method and make sure to weakly capture `self`. Calling `onChange(initial:perform:)` method in the initializer results in a runtime crash with the error message providing a migration guide. * New `powerOn()` and `powerOff()` methods to manually control `CBCentralManager` allocation. * Fixed an issue where characteristic access continuations where accidentally leaked. * Add new `ManufacturerIdentifier` model supporting parsing of manufacturer data in the advertisement. * Added `ConnectedDevices` environment model to retrieve all connected devices from the SwiftUI environment. * Add `Codable` conformance to all Characteristics. This PR contains breaking changes, requiring a major version bump. ## :books: Documentation Documentation was updated to reflect changed symbols (README currently points to 404 pages). Retrieving devices was documented with a small code examples. ## :white_check_mark: Testing Existing tests verify that refactoring did not break existing infrastructure. Additional test case was added to test retrieving peripherals and ensuring the new reference semantics do not break and peripherals are properly and expectedly deallocated. ## :pencil: Code of Conduct & Contributing Guidelines By submitting creating this pull request, you agree to follow our [Code of Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md): - [x] I agree to follow the [Code of Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work with the PR @Supereg!
Those are some great additions to the ecosystem. I had a few comments here and there but nothing major.
Main elements that might be high-level are:
- Identify if we have some "dead" code somewhere here in the package that we might want to remove before merging it. Some of the record access part might be strategically left in there for now as we aim to support this in the future.
- Identify where and how we want to use Swift Data for the elements here. As discussed in Slack, we might want to keep it for the required persistence layers but exploring the other options would be great if it stays within our available time.
Overall: Great work, excited to see this being integrated in a lot of apps!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the work here @Supereg!
Would be great if we can add some screenshots to the README & module documentations to provide some visual examples what is possible with this package.
Once the TODOs and PR checks are resolved I would be happy to see this PR merged; we can then provide follow-up improvements and other elements as we tag newer versions 🚀
As discussed, we will tackle all README changes in a follow-up PR. Tracked via #2 |
Moving some views to SpeziViews is tracked here StanfordSpezi/SpeziViews#40 |
Bluetooth Device Pairing Infrastructure and Health Measurements
♻️ Current situation & Problem
This is the initial PR for SpeziDevices. It introduces three targets
SpeziDevices
,SpeziDevicesUI
andSpeziOmron
.SpeziDevices provides device pairing and health measurements functionality for
BluetoothDevice
s implemented usingSpeziBluetooth
. SpeziDevicesUI provides UI components on top of that, e.g., visualizing paired devices, editing their information, showing nearby pairable devices, showing new health measurements, etc.SpeziOmron provides reusable implementations of Omron Bluetooth peripherals like the SC150 weight scale and the BP5250 blood pressure cuff.
⚙️ Release Notes
PairedDevices
module to manage paired devices. Discovering, pairing and connecting to them.HealthMeasurements
to manage health measurements from Bluetooth Devices and converting them to HealthKit samples.📚 Documentation
All targets contain DocC catalogs, documenting all their types.
✅ Testing
This PR adds extensive unit testing of components and has an UI Test app to test UI components.
📝 Code of Conduct & Contributing Guidelines
By submitting creating this pull request, you agree to follow our Code of Conduct and Contributing Guidelines: